using System.IO;
using System.Security.Cryptography;
using System.Text;
using System;

namespace Framework
{
    public static class RSAUtil
    {
        private static readonly int dwKeySize = 384;
        /// <summary>
        /// 获取非对称加密的公钥和私钥
        /// </summary>
        /// <param name="publicKey"></param>
        /// <param name="privateKey"></param>
        public static void GetNewKeys(out string publicKey, out string privateKey)
        {
            var provider = new RSACryptoServiceProvider(dwKeySize);
            publicKey = provider.ToXmlString(false);
            privateKey = provider.ToXmlString(true);
        }

        /// <summary>
        /// 使用公钥做加密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public static byte[] EncryptData(byte[] data, string publicKey)
        {
            if (string.IsNullOrEmpty(publicKey))
            {
                Logger.LogError($"RSAUtil.EncryptData, publicKey can not be null or empty!");
                return null;
            }
            if (null == data || 0 == data.Length)
            {
                Logger.LogError($"RSAUtil.EncryptData, data can not be null or empty!");
                return null;
            }
            var rsaProvider = new RSACryptoServiceProvider(dwKeySize);
            rsaProvider.FromXmlString(publicKey);
            return rsaProvider.Encrypt(data, false);
        }

        /// <summary>
        /// 使用私钥做解密
        /// </summary>
        /// <param name="data"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static byte[] DecryptData(byte[] data, string privateKey)
        {
            if (string.IsNullOrEmpty(privateKey))
            {
                Logger.LogError($"RSAUtil.EncryptData, publicKey can not be null or empty!");
                return null;
            }
            if (null == data || 0 == data.Length)
            {
                Logger.LogError($"RSAUtil.EncryptData, data can not be null or empty!");
                return null;
            }
            var rsaProvider = new RSACryptoServiceProvider(dwKeySize);
            rsaProvider.FromXmlString(privateKey);
            return rsaProvider.Decrypt(data, false);
        }

        /// <summary>
        /// 加密字符串
        /// </summary>
        /// <param name="data"></param>
        /// <param name="publicKey"></param>
        /// <returns></returns>
        public static string EncryptData(string data, string publicKey)
        {
            if (string.IsNullOrEmpty(data))
            {
                Logger.LogError($"RSAUtil.EncryptData, data can not be null or empty!");
                return null;
            }
            var bytes = StringHelper.Str2ByteArray(data);
            var enData = EncryptData(bytes, publicKey);
            return StringHelper.ByteArray2Str(enData);
        }

        /// <summary>
        /// 解密字符串
        /// </summary>
        /// <param name="data"></param>
        /// <param name="privateKey"></param>
        /// <returns></returns>
        public static string DecryptData(string data, string privateKey)
        {
            if (string.IsNullOrEmpty(data))
            {
                Logger.LogError($"RSAUtil.DecryptData, data can not be null or empty!");
                return null;
            }
            var bytes = StringHelper.Str2ByteArray(data);
            var enData = DecryptData(bytes, privateKey);
            return StringHelper.ByteArray2Str(enData);
        }

        /// <summary>
        /// 给hash数据签名
        /// </summary>
        /// <param name="md5Base64">md5算法返回的hash code, base64</param>
        /// <param name="privateKey">rsa私钥</param>
        /// <returns>签名之后的md5 base64格式</returns>
        public static string RSASignData(string md5Base64, string privateKey)
        {
            try
            {
                byte[] md5Data = StringHelper.Base64Str2ByteArray(md5Base64);
                RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
                rsaProvider.FromXmlString(privateKey);
                RSAPKCS1SignatureFormatter RSAFormatter = new RSAPKCS1SignatureFormatter(rsaProvider);
                //设置签名的算法为MD5 
                RSAFormatter.SetHashAlgorithm("MD5");
                //执行签名 
                var signedMd5Data = RSAFormatter.CreateSignature(md5Data);
                return Convert.ToBase64String(signedMd5Data);
            }
            catch (System.Exception exp)
            {
                Logger.LogException(exp);
                return null;
            }
        }

        /// <summary>
        /// 给hash数据签名
        /// </summary>
        /// <param name="md5Data">md5字节数组</param>
        /// <param name="privateKey">rsa私钥</param>
        /// <returns>签名之后的md5数据</returns>
        public static byte[] RSASignData(byte[] md5Data, string privateKey)
        {
            try
            {
                RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
                rsaProvider.FromXmlString(privateKey);
                RSAPKCS1SignatureFormatter rsaFormatter = new RSAPKCS1SignatureFormatter(rsaProvider);
                //设置签名的算法为MD5 
                rsaFormatter.SetHashAlgorithm("MD5");
                //执行签名 
                return rsaFormatter.CreateSignature(md5Data);
            }
            catch (System.Exception exp)
            {
                Logger.LogException(exp);
                return null;
            }
        }

        /// <summary>
        /// 验证数据签名
        /// </summary>
        /// <param name="md5Base64">当前md5值 base64</param>
        /// <param name="signMd564">签名之后的md5值 base64</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static bool RSASignCheck(string md5Base64, string signMd564, string publicKey)
        {
            try
            {
                byte[] md5Data = StringHelper.Base64Str2ByteArray(md5Base64);
                RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
                rsaProvider.FromXmlString(publicKey);

                RSAPKCS1SignatureDeformatter rsaDeFormatter = new RSAPKCS1SignatureDeformatter(rsaProvider);
                rsaDeFormatter.SetHashAlgorithm("MD5");
                byte[] rgbSignature = StringHelper.Base64Str2ByteArray(signMd564);
                if (rsaDeFormatter.VerifySignature(md5Data, rgbSignature))
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 验证数据签名
        /// </summary>
        /// <param name="md5Data">当前md5值 base64</param>
        /// <param name="rgbSignature">签名之后的md5值 base64</param>
        /// <param name="publicKey">公钥</param>
        /// <returns></returns>
        public static bool RSASignCheck(byte[] md5Data, byte[] rgbSignature, string publicKey)
        {
            try
            {
                RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
                rsaProvider.FromXmlString(publicKey);
                RSAPKCS1SignatureDeformatter rsaDeFormatter = new RSAPKCS1SignatureDeformatter(rsaProvider);
                rsaDeFormatter.SetHashAlgorithm("MD5");
                if (rsaDeFormatter.VerifySignature(md5Data, rgbSignature))
                {
                    return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }

    }
}